﻿namespace WorldView
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Threading;

    public class WorldMapper
    {
        // It should be TileTypeW enum but my hand hurts too much to fix.
        public static Dictionary<int, TileProperties> TileTypeWDefs;
        public static Dictionary<Color, int> colorTypeDefs = new Dictionary<Color,int>();

        private Dictionary<TileTypeW.TileType, List<Point>> tilesToSymbolize;

        private WorldHeader worldHeader;
        private WorldReader reader;

        private BinaryWriter writer;

        public static Block[,] tile;

        public static int t1 = 0;

        public static byte[] imagergb;
        public static byte[] Wallrgb;
        public WorldMapper()
        {
            TileTypeWDefs = new Dictionary<int, TileProperties>(255);

        }

        public WorldHeader Header
        {
            get
            {
                return this.worldHeader;
            }
        }

        /// <summary>
        /// Intiialize and load tile types
        /// </summary>
        public void Initialize()
        {
            // :OHGOD:
            TileTypeWDefs[0] = new TileProperties(TileTypeW.TileType.Dirt, false, Constants.Colors.DIRT);
            TileTypeWDefs[1] = new TileProperties(TileTypeW.TileType.Stone, false, Constants.Colors.STONE);
            TileTypeWDefs[2] = new TileProperties(TileTypeW.TileType.Grass, false, Constants.Colors.GRASS);
            TileTypeWDefs[3] = new TileProperties(TileTypeW.TileType.Plants, true, Constants.Colors.PLANTS);
            TileTypeWDefs[4] = new TileProperties(TileTypeW.TileType.Torches, false, Constants.Colors.LIGHT_SOURCE);
            TileTypeWDefs[5] = new TileProperties(TileTypeW.TileType.Trees, true, Constants.Colors.TREE);
            TileTypeWDefs[6] = new TileProperties(TileTypeW.TileType.Iron, false, Constants.Colors.IRON);
            TileTypeWDefs[7] = new TileProperties(TileTypeW.TileType.Copper, false, Constants.Colors.COPPER);
            TileTypeWDefs[8] = new TileProperties(TileTypeW.TileType.Gold, false, Constants.Colors.GOLD);
            TileTypeWDefs[9] = new TileProperties(TileTypeW.TileType.Silver, false, Constants.Colors.SILVER);

            TileTypeWDefs[10] = new TileProperties(TileTypeW.TileType.Door1, true, Constants.Colors.DOOR1);
            TileTypeWDefs[11] = new TileProperties(TileTypeW.TileType.Door2, true, Constants.Colors.DOOR1);
            TileTypeWDefs[12] = new TileProperties(TileTypeW.TileType.HeartStone, true, Constants.Colors.HEART, new Symbol("heart.png"));
            TileTypeWDefs[13] = new TileProperties(TileTypeW.TileType.Bottles, true, Constants.Colors.BOTTLE);
            TileTypeWDefs[14] = new TileProperties(TileTypeW.TileType.Table, true, Constants.Colors.TABLE);
            TileTypeWDefs[15] = new TileProperties(TileTypeW.TileType.Chair, true, Constants.Colors.CHAIR);
            TileTypeWDefs[16] = new TileProperties(TileTypeW.TileType.Anvil, true, Constants.Colors.ANVIL);
            TileTypeWDefs[17] = new TileProperties(TileTypeW.TileType.Furnance, true, Constants.Colors.FURNACE);
            TileTypeWDefs[18] = new TileProperties(TileTypeW.TileType.CraftingTable, true, Constants.Colors.CTABLE);
            TileTypeWDefs[19] = new TileProperties(TileTypeW.TileType.WoodenPlatform, false, Constants.Colors.WOODP);
            TileTypeWDefs[20] = new TileProperties(TileTypeW.TileType.PlantsDecorative, true, Constants.Colors.PLANTS);

            TileTypeWDefs[21] = new TileProperties(TileTypeW.TileType.Chest, true, Constants.Colors.CHEST, new Symbol("chest.png"));
            TileTypeWDefs[22] = new TileProperties(TileTypeW.TileType.CorruptionStone1, false, Constants.Colors.CORRUPTION_STONE);
            TileTypeWDefs[23] = new TileProperties(TileTypeW.TileType.CorruptionGrass, false, Constants.Colors.CORRUPTION_GRASS);
            TileTypeWDefs[24] = new TileProperties(TileTypeW.TileType.CorruptionPlants, true, Constants.Colors.CORRUPTION_GRASS);
            TileTypeWDefs[25] = new TileProperties(TileTypeW.TileType.CorruptionStone2, false, Constants.Colors.CORRUPTION_STONE2);
            TileTypeWDefs[26] = new TileProperties(TileTypeW.TileType.Altar, true, Constants.Colors.ALTAR, new Symbol("altar.png"));
            TileTypeWDefs[27] = new TileProperties(TileTypeW.TileType.Sunflower, true, Constants.Colors.SUNF);
            TileTypeWDefs[28] = new TileProperties(TileTypeW.TileType.Pot, true, Constants.Colors.POT);
            TileTypeWDefs[29] = new TileProperties(TileTypeW.TileType.PiggyBank, true, Constants.Colors.PBANK);
            TileTypeWDefs[30] = new TileProperties(TileTypeW.TileType.BlockWood, false, Constants.Colors.BLOCKW);

            TileTypeWDefs[31] = new TileProperties(TileTypeW.TileType.ShadowOrb, true, Constants.Colors.SORB, new Symbol("shadow.png"));
            TileTypeWDefs[32] = new TileProperties(TileTypeW.TileType.CorruptionVines, false, Constants.Colors.CORRUPTION_VINES);
            TileTypeWDefs[33] = new TileProperties(TileTypeW.TileType.Candle, true, Constants.Colors.CANDLE);
            TileTypeWDefs[34] = new TileProperties(TileTypeW.TileType.ChandlerCopper, true, Constants.Colors.CHC);
            TileTypeWDefs[35] = new TileProperties(TileTypeW.TileType.ChandlerSilver, true, Constants.Colors.CHS);
            TileTypeWDefs[36] = new TileProperties(TileTypeW.TileType.ChandlerGold, true, Constants.Colors.CHG);
            TileTypeWDefs[37] = new TileProperties(TileTypeW.TileType.Meterorite, false, Constants.Colors.METEORITE);
            TileTypeWDefs[38] = new TileProperties(TileTypeW.TileType.BlockStone, false, Constants.Colors.BLOCK_S);
            TileTypeWDefs[39] = new TileProperties(TileTypeW.TileType.BlockRedStone, false, Constants.Colors.BLOCKRS);
            TileTypeWDefs[40] = new TileProperties(TileTypeW.TileType.Clay, false, Constants.Colors.CLAY);

            TileTypeWDefs[41] = new TileProperties(TileTypeW.TileType.BlockBlueStone, false, Constants.Colors.DUNGEONB);
            TileTypeWDefs[42] = new TileProperties(TileTypeW.TileType.LightGlobe, true, Constants.Colors.LIGHTGL);
            TileTypeWDefs[43] = new TileProperties(TileTypeW.TileType.BlockGreenStone, false, Constants.Colors.DUNGEONG);
            TileTypeWDefs[44] = new TileProperties(TileTypeW.TileType.BlockPinkStone, false, Constants.Colors.DUNGEONP);
            TileTypeWDefs[45] = new TileProperties(TileTypeW.TileType.BlockGold, false, Constants.Colors.BLOCKGO);
            TileTypeWDefs[46] = new TileProperties(TileTypeW.TileType.BlockSilver, false, Constants.Colors.BLOCKSI);
            TileTypeWDefs[47] = new TileProperties(TileTypeW.TileType.BlockCopper, false, Constants.Colors.BLOCKCO);
            TileTypeWDefs[48] = new TileProperties(TileTypeW.TileType.Spikes, false, Constants.Colors.SPIKES);
            TileTypeWDefs[49] = new TileProperties(TileTypeW.TileType.CandleBlue, false, Constants.Colors.CANDLEB);
            TileTypeWDefs[50] = new TileProperties(TileTypeW.TileType.Books, true, Constants.Colors.BOOK);

            TileTypeWDefs[51] = new TileProperties(TileTypeW.TileType.Web, false, Constants.Colors.WEB);
            TileTypeWDefs[52] = new TileProperties(TileTypeW.TileType.Vines, false, Constants.Colors.VINE);
            TileTypeWDefs[53] = new TileProperties(TileTypeW.TileType.Sand, false, Constants.Colors.SAND);
            TileTypeWDefs[54] = new TileProperties(TileTypeW.TileType.Glass, false, Constants.Colors.GLASS);
            TileTypeWDefs[55] = new TileProperties(TileTypeW.TileType.Signs, true, Constants.Colors.SIGN);
            TileTypeWDefs[56] = new TileProperties(TileTypeW.TileType.Obsidian, false, Constants.Colors.OBSIDIAN);
            TileTypeWDefs[57] = new TileProperties(TileTypeW.TileType.Ash, false, Constants.Colors.ASH);
            TileTypeWDefs[58] = new TileProperties(TileTypeW.TileType.Hellstone, false, Constants.Colors.HELLSTONE);
            TileTypeWDefs[59] = new TileProperties(TileTypeW.TileType.Mud, false, Constants.Colors.MUD);
            TileTypeWDefs[60] = new TileProperties(TileTypeW.TileType.UndergroundJungleGrass, false, Constants.Colors.UNDERGROUNDJUNGLE_GRASS);

            TileTypeWDefs[61] = new TileProperties(TileTypeW.TileType.UndergroundJunglePlants, true, Constants.Colors.UNDERGROUNDJUNGLE_PLANTS);
            TileTypeWDefs[62] = new TileProperties(TileTypeW.TileType.UndergroundJungleVines, false, Constants.Colors.UNDERGROUNDJUNGLE_VINES);
            TileTypeWDefs[63] = new TileProperties(TileTypeW.TileType.GemSapphire, false, Constants.Colors.GEMS_S, new Symbol("gem_s.png"));
            TileTypeWDefs[64] = new TileProperties(TileTypeW.TileType.GemRuby, false, Constants.Colors.GEMS_R, new Symbol("gem_r.png"));
            TileTypeWDefs[65] = new TileProperties(TileTypeW.TileType.GemEmerald, false, Constants.Colors.GEMS_E, new Symbol("gem_e.png"));
            TileTypeWDefs[66] = new TileProperties(TileTypeW.TileType.GemTopaz, false, Constants.Colors.GEMS_T, new Symbol("gem_t.png"));
            TileTypeWDefs[67] = new TileProperties(TileTypeW.TileType.GemAmethyst, false, Constants.Colors.GEMS_A, new Symbol("gem_a.png"));
            TileTypeWDefs[68] = new TileProperties(TileTypeW.TileType.GemDiamond, false, Constants.Colors.GEMS_D, new Symbol("gem_d.png"));
            TileTypeWDefs[69] = new TileProperties(TileTypeW.TileType.UndergroundJungleThorns, false, Constants.Colors.UNDERGROUNDJUNGLE_THORNS);
            TileTypeWDefs[70] = new TileProperties(TileTypeW.TileType.UndergroundMushroomGrass, false, Constants.Colors.UNDERGROUNDMUSHROOM_GRASS);

            TileTypeWDefs[71] = new TileProperties(TileTypeW.TileType.UndergroundMushroomPlants, true, Constants.Colors.UNDERGROUNDMUSHROOM_PLANTS);
            TileTypeWDefs[72] = new TileProperties(TileTypeW.TileType.UndergroundMushroomTrees, true, Constants.Colors.UNDERGROUNDMUSHROOM_TREES);
            TileTypeWDefs[73] = new TileProperties(TileTypeW.TileType.Plants2, true, Constants.Colors.PLANTS);
            TileTypeWDefs[74] = new TileProperties(TileTypeW.TileType.Plants3, true, Constants.Colors.PLANTS);
            TileTypeWDefs[75] = new TileProperties(TileTypeW.TileType.BlockObsidian, false, Constants.Colors.BLOCKOB);
            TileTypeWDefs[76] = new TileProperties(TileTypeW.TileType.BlockHellstone, false, Constants.Colors.BLOCKHS);
            TileTypeWDefs[77] = new TileProperties(TileTypeW.TileType.UnderworldFurnance, true, Constants.Colors.UFURNACE);
            TileTypeWDefs[78] = new TileProperties(TileTypeW.TileType.DecorativePot, true, Constants.Colors.DPOT);
            TileTypeWDefs[79] = new TileProperties(TileTypeW.TileType.Bed, true, Constants.Colors.BED);
            TileTypeWDefs[80] = new TileProperties(TileTypeW.TileType.Cactus, false, Constants.Colors.CACTUS);
            TileTypeWDefs[81] = new TileProperties(TileTypeW.TileType.Coral, true, Constants.Colors.CORAL);
            TileTypeWDefs[82] = new TileProperties(TileTypeW.TileType.HerbSprout, true, Constants.Colors.HERBSP);
            TileTypeWDefs[83] = new TileProperties(TileTypeW.TileType.HerbStalk, true, Constants.Colors.HERBST);
            TileTypeWDefs[84] = new TileProperties(TileTypeW.TileType.Herb, true, Constants.Colors.HERB);
            TileTypeWDefs[85] = new TileProperties(TileTypeW.TileType.Tombstone, true, Constants.Colors.TOMBSTONE);
            TileTypeWDefs[86] = new TileProperties(TileTypeW.TileType.Unknown, false, Constants.Colors.UNKNOWN);

            for (int i = Constants.MaxBlocks; i < 255; i++)
            {
                TileTypeWDefs[i] = new TileProperties(TileTypeW.TileType.Unknown, false,Color.Magenta);
            }

            TileTypeWDefs[256] = new TileProperties(TileTypeW.TileType.Sky, false, Constants.Colors.SKY);
            TileTypeWDefs[257] = new TileProperties(TileTypeW.TileType.Water, false, Constants.Colors.WATER);
            TileTypeWDefs[258] = new TileProperties(TileTypeW.TileType.Lava, false, Constants.Colors.LAVA);

            // Walls
            TileTypeWDefs[259] = new TileProperties(TileTypeW.TileType.WallStone, false, Constants.Colors.WALL_STONE);
            TileTypeWDefs[260] = new TileProperties(TileTypeW.TileType.WallDirt, false, Constants.Colors.WALL_DIRT);
            TileTypeWDefs[261] = new TileProperties(TileTypeW.TileType.WallStone2, false, Constants.Colors.WALL_STONE2);
            TileTypeWDefs[262] = new TileProperties(TileTypeW.TileType.WallWood, false, Constants.Colors.WALL_WOOD);
            TileTypeWDefs[263] = new TileProperties(TileTypeW.TileType.WallBrick, false, Constants.Colors.WALL_BRICK);
            TileTypeWDefs[264] = new TileProperties(TileTypeW.TileType.WallRed, false, Constants.Colors.WALL_BRICKR);
            TileTypeWDefs[265] = new TileProperties(TileTypeW.TileType.WallBlue, false, Constants.Colors.WALL_BRICKB);
            TileTypeWDefs[266] = new TileProperties(TileTypeW.TileType.WallGreen, false, Constants.Colors.WALL_BRICKG);
            TileTypeWDefs[267] = new TileProperties(TileTypeW.TileType.WallPink, false, Constants.Colors.WALL_BRICKP);
            TileTypeWDefs[268] = new TileProperties(TileTypeW.TileType.WallGold, false, Constants.Colors.WALL_BRICKGO);
            TileTypeWDefs[269] = new TileProperties(TileTypeW.TileType.WallSilver, false, Constants.Colors.WALL_BRICKS);
            TileTypeWDefs[270] = new TileProperties(TileTypeW.TileType.WallCopper, false, Constants.Colors.WALL_BRICKC);
            TileTypeWDefs[271] = new TileProperties(TileTypeW.TileType.WallHellstone, false, Constants.Colors.WALL_BRICKHS);
            TileTypeWDefs[272] = new TileProperties(TileTypeW.TileType.WallHellstone, false, Constants.Colors.WALL_BACKGROUND);

            //color defs
            colorTypeDefs.Add( Constants.Colors.DIRT, 0);
            colorTypeDefs.Add( Constants.Colors.STONE, 1);
            colorTypeDefs.Add( Constants.Colors.GRASS, 2);
            colorTypeDefs.Add( Constants.Colors.PLANTS,3);
            colorTypeDefs.Add( Constants.Colors.LIGHT_SOURCE, 4);
            colorTypeDefs.Add( Constants.Colors.TREE, 5);
            colorTypeDefs.Add( Constants.Colors.IRON, 6);
            colorTypeDefs.Add( Constants.Colors.COPPER, 7);
            colorTypeDefs.Add( Constants.Colors.GOLD, 8);
            colorTypeDefs.Add( Constants.Colors.SILVER, 9);

            colorTypeDefs.Add( Constants.Colors.DOOR1, 10);
            colorTypeDefs.Add( Constants.Colors.DOOR2, 11);
            colorTypeDefs.Add( Constants.Colors.HEART, 12);
            colorTypeDefs.Add( Constants.Colors.BOTTLE, 13);
            colorTypeDefs.Add( Constants.Colors.TABLE, 14);
            colorTypeDefs.Add( Constants.Colors.CHAIR, 15);
            colorTypeDefs.Add( Constants.Colors.ANVIL, 16);
            colorTypeDefs.Add( Constants.Colors.FURNACE,17 );
            colorTypeDefs.Add( Constants.Colors.CTABLE, 18);
            colorTypeDefs.Add( Constants.Colors.WOODP, 19);
            //colorTypeDefs.Add( Constants.Colors.PLANTS, 20);

            colorTypeDefs.Add( Constants.Colors.CHEST, 21);
            colorTypeDefs.Add( Constants.Colors.CORRUPTION_STONE, 22);
            colorTypeDefs.Add( Constants.Colors.CORRUPTION_GRASS, 23);
            //colorTypeDefs.Add( Constants.Colors.CORRUPTION_GRASS, 24);
            colorTypeDefs.Add( Constants.Colors.CORRUPTION_STONE2, 25);
            colorTypeDefs.Add( Constants.Colors.ALTAR, 26);
            colorTypeDefs.Add( Constants.Colors.SUNF, 27);
            colorTypeDefs.Add( Constants.Colors.POT, 28);
            colorTypeDefs.Add( Constants.Colors.PBANK,29 );
            colorTypeDefs.Add( Constants.Colors.BLOCKW, 30);

            colorTypeDefs.Add( Constants.Colors.SORB, 31);
            colorTypeDefs.Add( Constants.Colors.CORRUPTION_VINES, 32);
            colorTypeDefs.Add( Constants.Colors.CANDLE, 33);
            colorTypeDefs.Add( Constants.Colors.CHC, 34);
            colorTypeDefs.Add( Constants.Colors.CHS, 35);
            colorTypeDefs.Add( Constants.Colors.CHG, 36);
            colorTypeDefs.Add( Constants.Colors.METEORITE, 37);
            colorTypeDefs.Add( Constants.Colors.BLOCK_S, 38);
            colorTypeDefs.Add( Constants.Colors.BLOCKRS, 39);
            colorTypeDefs.Add( Constants.Colors.CLAY, 40);

            colorTypeDefs.Add( Constants.Colors.DUNGEONB,41 );
            colorTypeDefs.Add( Constants.Colors.LIGHTGL, 42);
            colorTypeDefs.Add( Constants.Colors.DUNGEONG, 43);
            colorTypeDefs.Add( Constants.Colors.DUNGEONP, 44);
            colorTypeDefs.Add( Constants.Colors.BLOCKGO, 45);
            colorTypeDefs.Add( Constants.Colors.BLOCKSI, 46);
            colorTypeDefs.Add( Constants.Colors.BLOCKCO, 47);
            colorTypeDefs.Add( Constants.Colors.SPIKES, 48);
            colorTypeDefs.Add( Constants.Colors.CANDLEB,49 );
            colorTypeDefs.Add( Constants.Colors.BOOK, 50);

            colorTypeDefs.Add( Constants.Colors.WEB, 51);
            colorTypeDefs.Add( Constants.Colors.VINE, 52);
            colorTypeDefs.Add( Constants.Colors.SAND, 53);
            colorTypeDefs.Add( Constants.Colors.GLASS, 54);
            colorTypeDefs.Add( Constants.Colors.SIGN, 55);
            colorTypeDefs.Add( Constants.Colors.OBSIDIAN, 56);
            colorTypeDefs.Add( Constants.Colors.ASH, 57);
            colorTypeDefs.Add( Constants.Colors.HELLSTONE, 58);
            colorTypeDefs.Add( Constants.Colors.MUD, 59);
            colorTypeDefs.Add( Constants.Colors.UNDERGROUNDJUNGLE_GRASS, 60);

            //colorTypeDefs.Add( Constants.Colors.UNDERGROUNDJUNGLE_PLANTS, 61);
            colorTypeDefs.Add( Constants.Colors.UNDERGROUNDJUNGLE_VINES, 62);
            colorTypeDefs.Add( Constants.Colors.GEMS_S, 63);
            colorTypeDefs.Add( Constants.Colors.GEMS_R, 64);
            colorTypeDefs.Add( Constants.Colors.GEMS_E, 65);
            colorTypeDefs.Add( Constants.Colors.GEMS_T, 66);
            colorTypeDefs.Add( Constants.Colors.GEMS_A, 67);
            colorTypeDefs.Add( Constants.Colors.GEMS_D, 68);
            colorTypeDefs.Add( Constants.Colors.UNDERGROUNDJUNGLE_THORNS, 69);
            colorTypeDefs.Add( Constants.Colors.UNDERGROUNDMUSHROOM_GRASS,70 );

            colorTypeDefs.Add( Constants.Colors.UNDERGROUNDMUSHROOM_PLANTS, 71);
            colorTypeDefs.Add( Constants.Colors.UNDERGROUNDMUSHROOM_TREES, 72);
            //colorTypeDefs.Add( Constants.Colors.PLANTS, 73);
            //colorTypeDefs.Add( Constants.Colors.PLANTS, 74);
            colorTypeDefs.Add( Constants.Colors.BLOCKOB, 75);
            colorTypeDefs.Add( Constants.Colors.BLOCKHS, 76);
            colorTypeDefs.Add( Constants.Colors.UFURNACE, 77);
            colorTypeDefs.Add( Constants.Colors.DPOT, 78);
            colorTypeDefs.Add( Constants.Colors.BED, 79);
            colorTypeDefs.Add( Constants.Colors.CACTUS, 80);
            colorTypeDefs.Add( Constants.Colors.CORAL, 81);
            colorTypeDefs.Add( Constants.Colors.HERBSP, 82);
            colorTypeDefs.Add(Constants.Colors.HERBST, 83);
            colorTypeDefs.Add(Constants.Colors.HERB, 84);
            colorTypeDefs.Add(Constants.Colors.TOMBSTONE, 85);

            //for (int i = Constants.MaxBlocks; i < 255; i++)
            //{
                colorTypeDefs.Add(Color.Magenta,255);
            //}

            colorTypeDefs.Add( Constants.Colors.SKY,  256);
            colorTypeDefs.Add( Constants.Colors.WATER, 257);
            colorTypeDefs.Add( Constants.Colors.LAVA, 258);

            // Walls);
            colorTypeDefs.Add( Constants.Colors.WALL_STONE, 259 );
            colorTypeDefs.Add( Constants.Colors.WALL_DIRT, 260);
            colorTypeDefs.Add( Constants.Colors.WALL_STONE2, 261);
            colorTypeDefs.Add( Constants.Colors.WALL_WOOD, 262);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICK, 263);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKR, 264);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKB, 265);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKG, 266);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKP, 267);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKGO, 268);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKS, 269);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKC, 270);
            colorTypeDefs.Add( Constants.Colors.WALL_BRICKHS, 271);
            colorTypeDefs.Add(Constants.Colors.WALL_BACKGROUND, 272);










        }

        public void OpenWorld(string worldPath)
        {
            reader = new WorldReader(worldPath);
            this.worldHeader = reader.ReadHeader();

        }

        public void CreatePreviewPNG(string outputPngPath, bool canDrawWalls, bool canDrawSymbols, ProgressBar progressBar, string CFile, string SFile, string NFile, string WFile, PictureBox world, PictureBox wall)
        {

            int maxX = (int)Header.MaxTiles.Y;
            int maxY = (int)Header.MaxTiles.X;
            TileTypeW[,] tiles = new TileTypeW[maxX,maxY];
            this.reader.SeekToTiles();
            for (int i = 0; i < maxX; i++)
            {
                for (int k = 0; k < maxY; k++)
                {
                    tiles[i, k] = this.reader.GetNextTile();
                }
            }
            // Reset Symbol List
            tilesToSymbolize = new Dictionary<TileTypeW.TileType, List<Point>>();

            //byte[,] pixels = new byte[cols, rows];

            Bitmap bitmap = new Bitmap(maxX, maxY, PixelFormat.Format24bppRgb);
            Bitmap bitmapW = new Bitmap(maxX, maxY, PixelFormat.Format24bppRgb);
            Graphics graphicsHandle = Graphics.FromImage(bitmap);
            Graphics graphicsHandleW = Graphics.FromImage(bitmapW);
            graphicsHandle.FillRectangle(new SolidBrush(Constants.Colors.SKY), 0, 0, bitmap.Width, bitmap.Height);
            graphicsHandleW.FillRectangle(new SolidBrush(Constants.Colors.SKY), 0, 0, bitmapW.Width,(int) this.worldHeader.SurfaceLevel);
            graphicsHandleW.FillRectangle(new SolidBrush(Constants.Colors.WALL_STONE), 0, (int)this.worldHeader.RockLayer, bitmapW.Width, (int)(this.worldHeader.SurfaceLevel - bitmapW.Height));

            Dictionary<byte, Color> randomColors = new Dictionary<byte, Color>();
            Random random = new Random();
            TileProperties properties;


            for (int col = 0; col < maxX; col++)
            {
                progressBar.Value = (int)(((float)col / (float)maxX) * 100.0f);
                for (int row = 0; row < maxY; row++)
                {

                    TileTypeW TileTypeW = tiles[col,row];
                    if (TileTypeW.t == TileTypeW.TileType.Sky && row > (int)this.Header.SurfaceLevel)
                    {
                        TileTypeW.t = TileTypeW.TileType.WallBackground;
                    }


                    if (TileTypeW.Wallt == WorldView.TileTypeW.TileType.Unknown)
                    {
                        if (row < worldHeader.SurfaceLevel)
                        {
                            TileTypeW.Wallt = WorldView.TileTypeW.TileType.Sky;
                        }
                        if (row > worldHeader.SurfaceLevel)
                        {
                            TileTypeW.Wallt = WorldView.TileTypeW.TileType.WallStone;
                        }
                    }


                    // Else Set Pixel Value
                    //Color[] Wall = { Constants.Colors.WALL_BACKGROUND, Constants.Colors.WALL_BRICK, Constants.Colors.WALL_BRICKB, Constants.Colors.WALL_BRICKC, Constants.Colors.WALL_BRICKG, Constants.Colors.WALL_BRICKGO, Constants.Colors.WALL_BRICKHS, Constants.Colors.WALL_BRICKP, Constants.Colors.WALL_BRICKR, Constants.Colors.WALL_BRICKS, Constants.Colors.WALL_DIRT, Constants.Colors.WALL_STONE, Constants.Colors.WALL_STONE2, Constants.Colors.WALL_WOOD };
                    Color c = TileTypeWDefs[(int)TileTypeW.Wallt].Colour;
                    Color c2 = TileTypeWDefs[(int)TileTypeW.t].Colour;
                    if (c2 == Constants.Colors.CHEST || TileTypeW.t == TileTypeW.TileType.Chest)
                    {
                        int why = 0;
                    }
                    bitmapW.SetPixel(col, row,c);
                    bitmap.SetPixel(col, row, c2);
            }
                
            }

            reader.GetRest(CFile,SFile,NFile);


            // Spawn
            Bitmap spawnSymbol = new Symbol("spawn.png").BMP;
            int spawnX = Math.Max((int)this.Header.SpawnPoint.X - (spawnSymbol.Width / 2), 0);
            int spawnY = Math.Max((int)this.Header.SpawnPoint.Y - (spawnSymbol.Height / 2), 0);
            if (canDrawSymbols)
            {

                graphicsHandle.DrawImage(spawnSymbol, spawnX, spawnY);
            }
            else
            {
                bitmap.SetPixel(spawnX, spawnY, Constants.Colors.SPAWN);
            }
            //graphicsHandle.FillRectangle(new SolidBrush(Constants.Colors.SKY), 0, 0, bitmap.Width, 20);
            bitmap.Save(outputPngPath, ImageFormat.Png);
            if (WFile != "")
            {
                bitmapW.Save(WFile, ImageFormat.Png);
            }
            progressBar.Value = 100;

            world.Image = bitmap;
            wall.Image = bitmapW;
        }

        public void CloseWorld()
        {
            reader.Close();
        }

        public void AnalyseWorld(string WorldName, int Number, int id, int spawnX, int spawnY, string output, bool boss1, bool boss2, bool boss3, System.ComponentModel.BackgroundWorker progressBar, string file, int sLv, int rLv, Varies v, string file2)
        {
            //FileStream streamI = new FileStream(file, FileMode.Open);
            //FileStream streamI2 = new FileStream(file2, FileMode.Open);
            Bitmap image = new Bitmap(file);
            Bitmap WallI = new Bitmap(file2);
            FileStream stream = new FileStream(output, FileMode.Create);
            writer = new BinaryWriter(stream);
            stream.Seek(0, SeekOrigin.Begin);
            tile = new Block[image.Width, image.Height];

            for (int i = 0; i < image.Width; i++)
            {
                for (int k = 0; k < image.Height; k++)
                {
                    Block b = new Block();
                    tile[i, k] = b;
                }
            }
            int spawningX = spawnX;
            int spawningY = spawnY;

            Rectangle imageRect = new Rectangle(0, 0, image.Width, image.Height);
            Rectangle WallRect = new Rectangle(0, 0, WallI.Width, WallI.Height);

            System.Drawing.Imaging.BitmapData imageData = image.LockBits(imageRect, System.Drawing.Imaging.ImageLockMode.ReadWrite, image.PixelFormat);
            System.Drawing.Imaging.BitmapData WallData = WallI.LockBits(imageRect, System.Drawing.Imaging.ImageLockMode.ReadWrite, WallI.PixelFormat);

            IntPtr imagePtr = imageData.Scan0;
            IntPtr WallPtr = WallData.Scan0;

            int imageBytes = Math.Abs(imageData.Stride) * image.Height;
            int WallBytes = Math.Abs(WallData.Stride) * WallI.Height;

            imagergb = new byte[imageBytes];
            Wallrgb = new byte[WallBytes];

            System.Runtime.InteropServices.Marshal.Copy(imagePtr, imagergb, 0, imageBytes);
            System.Runtime.InteropServices.Marshal.Copy(WallPtr, Wallrgb, 0, WallBytes);

            image.UnlockBits(imageData);
            WallI.UnlockBits(WallData);
            int maxX = image.Width;
            int maxY = image.Height;

            image.Dispose();
            WallI.Dispose();
            int index = -3;
            int indexAdd = 3;

            int indexW = -3;
            int indexAddW = 3;

            bool Alpha = true;
            bool AlphaW = true;

            for (int i = 3; i <imagergb.Length && Alpha; i += 4)
            {
                if (imagergb[i] != 255)
                {
                    if (imagergb[i] != 0)
                    {
                        Alpha = false;
                    }
                }
            }
            if (Alpha)
            {
                index = -4;
                indexAdd = 4;
            }

            for (int i = 3; i < Wallrgb.Length && AlphaW; i += 4)
            {
                if (Wallrgb[i] != 255)
                {
                    if (Wallrgb[i] != 0)
                    {
                        AlphaW = false;
                    }
                }
            }
            if (AlphaW)
            {
                indexW = -4;
                indexAddW = 4;
            }

            for (int row = 0; row < maxY; row++)
            {
                progressBar.ReportProgress((int)(((float)row / (float)maxY) * 98.0f));
                for (int col = 0; col < maxX; col++)
                {
                    index += indexAdd;
                    indexW += indexAddW;
                    Color pix = Color.FromArgb(imagergb[index + 2], imagergb[index + 1], imagergb[index]);
                    Color Wpix = Color.FromArgb(Wallrgb[indexW + 2], Wallrgb[indexW + 1], Wallrgb[indexW]);
                    //blockIndex ++;
                    //int row = (int)(blockIndex / 8400);
                    //int col = (blockIndex - (row * 8400));
                    Block block = tile[col, row];

                    int by = 0;
                    int byW = 0;

                    if (pix == Constants.Colors.SPAWN)
                    {
                        spawningX = col;
                        spawningY = row;
                        continue;
                    }
                    try
                    {
                        by = colorTypeDefs[pix];
                    }
                    catch (KeyNotFoundException e)
                    {
                        by = 0;
                        block.active = false;
                    }
                        try
                        {
                            byW = colorTypeDefs[Wpix];
                        }
                        catch (KeyNotFoundException e)
                        {
                            byW = 0;
                        }

                    if (pix == Constants.Colors.UNKNOWN || pix == Constants.Colors.UNKNOWN)
                    {
                        block.Tilebyte = 0;
                    }

                    if (Wpix == Constants.Colors.UNKNOWN || Wpix == Constants.Colors.UNKNOWN)
                    {
                        block.wallbyte = 0;
                    }

                    if (pix == Constants.Colors.WATER)
                    {
                        block.liquid = true;
                        block.level = 255;
                    }
                    if (pix == Constants.Colors.LAVA)
                    {
                        block.liquid = true;
                        block.lava = true;
                        block.light = true;
                        block.level = 255;
                    }

                    if (pix == Constants.Colors.CORAL)
                    {
                        block.liquid = true;
                    }

                    Color[] Wall = { Constants.Colors.WALL_BACKGROUND, Constants.Colors.WALL_BRICK, Constants.Colors.WALL_BRICKB, Constants.Colors.WALL_BRICKC, Constants.Colors.WALL_BRICKG, Constants.Colors.WALL_BRICKGO, Constants.Colors.WALL_BRICKHS, Constants.Colors.WALL_BRICKP, Constants.Colors.WALL_BRICKR, Constants.Colors.WALL_BRICKS, Constants.Colors.WALL_DIRT, Constants.Colors.WALL_STONE, Constants.Colors.WALL_STONE2, Constants.Colors.WALL_WOOD };
                    if (Array.Exists(Wall, elements => elements.Equals(Wpix)))
                    {
                        block.wall = true;
                        //active = false;
                        byW -= Constants.WallOffset;
                    }
                    string pixS = pix.ToString();
                    pixS = pixS.ToLower();

                    if (pix == Constants.Colors.SKY || pix == Constants.Colors.LAVA || pix == Constants.Colors.WATER)
                    {
                        block.active = false;
                        
                    }
                    if (pix == Constants.Colors.SKY)
                    {
                        block.light = true;
                    }

                    if (by > Constants.MaxBlocks)
                    {
                        block.active = false;
                        by = 0;
                    }
                    block.Tilebyte = (byte)by;
                    block.wallbyte = (byte)byW;

                    WorldMapper.tile[col, row] = block;
                }

            }
             
            //write frames
            for (int row = 0; row < maxY; row++)
            {
           
                for (int col = 0; col < maxX; col++)
                {
                    Block block = tile[col, row];
                    Random genRand = new Random();
                    //for all tiles, assume a top left starting point, cus that is where is will start.
                    Color[] twobytwo = { Constants.Colors.HEART, Constants.Colors.CHEST, Constants.Colors.SORB};
                    Color[] onebytwo = { Constants.Colors.CTABLE, Constants.Colors.PBANK, Constants.Colors.ANVIL };
                    Color[] threebytwo = { Constants.Colors.FURNACE, Constants.Colors.UFURNACE, Constants.Colors.TABLE, Constants.Colors.BED };
                    //2x2 standard
                    if (Array.Exists(twobytwo, elements => elements.Equals(WorldMapper.TileTypeWDefs[block.Tilebyte].colour)))
                    {
                        bool isComplete = check2x2(col, row);

                        if (!isComplete)
                        {
                            continue;
                        }
                        tile[col, row].changeFrame(0, 0);
                        tile[col, row + 1].changeFrame(0, 18);
                        tile[col + 1, row].changeFrame(18, 0);
                        tile[col + 1, row + 1].changeFrame(18, 18);
                    }

                    //1x2 standard
                    if (Array.Exists(onebytwo, elements => elements.Equals(WorldMapper.TileTypeWDefs[block.Tilebyte].colour)))
                    {
                        bool isComplete = check1x2(col, row);

                        if (!isComplete)
                        {
                            continue;
                        }
                        tile[col, row].changeFrame(0, 0);
                        tile[col + 1, row].changeFrame(18, 0);
                    }

                    //3x2 standard
                    if (Array.Exists(threebytwo, elements => elements.Equals(WorldMapper.TileTypeWDefs[block.Tilebyte].colour)))
                    {
                        bool isComplete = check3x2(col, row);

                        if (!isComplete)
                        {
                            continue;
                        }
                        tile[col, row].changeFrame(0, 0);
                        tile[col + 1, row].changeFrame(18, 0);
                        tile[col + 2, row].changeFrame(36, 0);
                        tile[col, row + 1].changeFrame(0, 18);
                        tile[col + 1, row + 1].changeFrame(18, 18);
                        tile[col + 2, row + 1].changeFrame(36, 18);
                    }

                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.CHAIR)
                    {
                        if (WorldMapper.TileTypeWDefs[tile[col, row + 1].Tilebyte].colour != Constants.Colors.CHAIR)
                        {
                            continue;
                        }
                        if (WorldMapper.TileTypeWDefs[tile[col - 1, row].Tilebyte].colour != Constants.Colors.TABLE)
                        {
                            tile[col, row].changeFrame(0, 0);
                            tile[col, row + 1].changeFrame(0, 18);
                        }
                        else
                        {
                            tile[col, row].changeFrame(18, 0);
                            tile[col, row + 1].changeFrame(18, 18);
                        }
                    }
                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.POT)
                    {
                        bool isComplete = check2x2(col, row);

                        if (!isComplete)
                        {
                            continue;
                        }
                        short[] posX12 = {0,36,72};
                        short[] posX34 = {18,54,90};
                        tile[col, row].changeFrame(posX12[genRand.Next(2)], 0);
                        tile[col, row + 1].changeFrame(posX12[genRand.Next(2)], 18);
                        tile[col + 1, row].changeFrame(posX34[genRand.Next(2)], 0);
                        tile[col + 1, row + 1].changeFrame(posX34[genRand.Next(2)], 18);
                    }

                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.PLANTS)
                    {
                        tile[col, row].changeFrame((short)(genRand.Next(3) * 36), 0);
                    }
                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.CORRUPTION_GRASS)
                    {
                        tile[col, row].changeFrame((short)(genRand.Next(3) * 36), 0);
                    }

                    

                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.UNDERGROUNDJUNGLE_PLANTS)
                    {
                        if (genRand.Next(100) < 30)
                        {
                            tile[col, row].changeFrame(108, 0);
                        }
                        else
                        {
                            tile[col, row].changeFrame(144, 0);
                        }

                    }

                    //Analyse and making trees
                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.TREE)
                    {
                        if (block.framelock)
                        {
                            continue;
                        }
                        int baseY = 0;
                        int baseX = 0;
                        Block Tbase = null;
                        //First, find the bottom of the tree.
                        if (WorldMapper.TileTypeWDefs[tile[col + 1, row].Tilebyte].colour == Constants.Colors.TREE)
                        {
                            if (WorldMapper.TileTypeWDefs[tile[col + 1, row + 1].Tilebyte].colour == Constants.Colors.TREE)
                            {
                                int k = 1;
                                while (WorldMapper.TileTypeWDefs[tile[col + 1, row + k].Tilebyte].colour == Constants.Colors.TREE)
                                {
                                    k++;
                                }
                                k--;
                                Tbase = tile[col + 1, row + k];
                                baseX = col + 1;
                                baseY = row + k;
                            }
                        }
                        else
                        {
                            
                            int k = 1;
                            while (WorldMapper.TileTypeWDefs[tile[col, row + k].Tilebyte].colour == Constants.Colors.TREE)
                            {
                                k++;
                            }
                            k--;
                            Tbase = tile[col, row + k];
                            baseX = col;
                            baseY = row + k;
                        }

                        if (baseX == 0 && baseY == 0)
                        {
                            continue;
                        }
                        //Now that roots are done, we can make the rest


                        for (int k = 1; WorldMapper.TileTypeWDefs[tile[baseX, baseY - k].Tilebyte].colour == Constants.Colors.TREE; k++)
                        {
                            Boolean leftOff = false;
                            Boolean rightOff = false;
                            Block currT = tile[baseX, baseY - k];
                            if (WorldMapper.TileTypeWDefs[tile[baseX, (baseY - k) - 1].Tilebyte].colour != Constants.Colors.TREE)
                            {
                                currT.frameX = 22;
                                switch (genRand.Next(2))
                                {
                                    case 0:
                                        currT.frameY = 198;
                                        break;
                                    case 1:
                                        currT.frameY = 220;
                                        break;
                                    case 2:
                                        currT.frameY = 242;
                                        break;

                                }
                                if (genRand.Next(100) > 90)
                                {
                                    currT.frameY = 0;
                                }
                               
                            }
                            else
                            {
                                switch (genRand.Next(2))
                                {
                                    case 0:
                                        currT.frameX = 0;
                                        break;
                                    case 1:
                                        currT.frameX = 22;
                                        break;
                                    case 2:
                                        currT.frameX = 44;
                                        break;

                                }
                                switch (genRand.Next(5))
                                {
                                    case 0:
                                        currT.frameY = 0;
                                        break;
                                    case 1:
                                        currT.frameY = 66;
                                        break;
                                    case 2:
                                        currT.frameY = 110;
                                        break;
                                    case 3:
                                        currT.frameY = 22;
                                        break;
                                    case 4:
                                        currT.frameY = 88;
                                        break;
                                    case 5:
                                        currT.frameY = 44;
                                        break;

                                }
                                
                            }
                            if (WorldMapper.TileTypeWDefs[tile[baseX - 1, baseY - k].Tilebyte].colour == Constants.Colors.TREE)
                            {
                                currT.frameX = 88;
                                currT.frameY = 0;
                                switch (genRand.Next(1))
                                {
                                    case 0:
                                        tile[baseX - 1, baseY - k].frameX = 44;
                                        switch (genRand.Next(2))
                                        {
                                            case 0:
                                                tile[baseX - 1, baseY - k].frameY = 198;
                                                break;
                                            case 1:
                                                tile[baseX - 1, baseY - k].frameY = 242;
                                                break;
                                            case 2:
                                                tile[baseX - 1, baseY - k].frameY = 220;
                                                break;
                                        }
                                        break;
                                    case 1:
                                        tile[baseX - 1, baseY - k].frameX = 66;
                                        switch (genRand.Next(2))
                                        {
                                            case 0:
                                                tile[baseX - 1, baseY - k].frameY = 0;
                                                break;
                                            case 1:
                                                tile[baseX - 1, baseY - k].frameY = 22;
                                                break;
                                            case 2:
                                                tile[baseX - 1, baseY - k].frameY = 44;
                                                break;
                                        }
                                        break;
                                }
                                
                                leftOff = true;
                                tile[baseX - 1, baseY - k].framelock = true;
                            }
                            if (WorldMapper.TileTypeWDefs[tile[baseX + 1, baseY - k].Tilebyte].colour == Constants.Colors.TREE)
                            {
                                currT.frameX = 66;
                                currT.frameY = 66;
                                if (leftOff)
                                {
                                    currT.frameX = 110;
                                    currT.frameY = 66;
                                }
                                switch (genRand.Next(1))
                                {
                                    case 0:
                                        tile[baseX + 1, baseY - k].frameX = 66;
                                        switch (genRand.Next(2))
                                        {
                                            case 0:
                                                tile[baseX + 1, baseY - k].frameY = 242;
                                                break;
                                            case 1:
                                                tile[baseX + 1, baseY - k].frameY = 220;
                                                break;
                                            case 2:
                                                tile[baseX + 1, baseY - k].frameY = 198;
                                                break;
                                        }
                                        break;
                                    case 1:
                                        tile[baseX + 1, baseY - k].frameX = 88;
                                        switch (genRand.Next(2))
                                        {
                                            case 0:
                                                tile[baseX + 1, baseY - k].frameY = 110;
                                                break;
                                            case 1:
                                                tile[baseX + 1, baseY - k].frameY = 88;
                                                break;
                                            case 2:
                                                tile[baseX + 1, baseY - k].frameY = 66;
                                                break;
                                        }
                                        break;
                                }
                                rightOff = true;
                                tile[baseX + 1, baseY - k].framelock = true;
                                currT.framelock = true;
                            }


                            
                        }
                        //Have base, make roots
                        Boolean leftBase = false;
                        Boolean rightBase = false;
                        short[] bases = { 154, 176, 134, 132 };
                        if (WorldMapper.TileTypeWDefs[tile[baseX - 1, baseY].Tilebyte].colour == Constants.Colors.TREE)
                        {
                            Tbase.frameX = 66;
                            tile[baseX - 1, baseY].changeFrame(44, bases[genRand.Next(3)]);
                            leftBase = true;
                        }
                        if (WorldMapper.TileTypeWDefs[tile[baseX + 1, baseY].Tilebyte].colour == Constants.Colors.TREE)
                        {
                            if (leftBase)
                            {
                                Tbase.frameX = 88;

                            }
                            else
                            {
                                Tbase.frameX = 0;
                            }

                            tile[baseX + 1, baseY].changeFrame(22, bases[genRand.Next(3)]);
                            rightBase = true;
                        }

                        Tbase.frameY = 132;
                        if (!leftBase && !rightBase)
                        {
                            Tbase.frameX = 0;
                            Tbase.frameY = 0;
                        }
                        Tbase.framelock = true;
                        if (tile[baseX, baseY + 1].Tilebyte != 60 || tile[baseX, baseY + 1].Tilebyte != 23)
                        {
                            tile[baseX, baseY + 1].Tilebyte = 2;
                        }
                        if (tile[baseX + 1, baseY + 1].Tilebyte != 60 || tile[baseX + 1, baseY + 1].Tilebyte != 23)
                        {
                            tile[baseX + 1, baseY + 1].Tilebyte = 2;
                        }
                        if (tile[baseX - 1, baseY + 1].Tilebyte != 60 || tile[baseX - 1, baseY + 1].Tilebyte != 23)
                        {
                            tile[baseX - 1, baseY + 1].Tilebyte = 2;
                        }
                    }
                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.UNDERGROUNDMUSHROOM_TREES)
                    {
                        switch(genRand.Next(1))
                        {
                            case 0:
                                tile[col, row].frameX = 18;
                                break;
                            case 1:
                                tile[col, row].frameX = 36;
                                break;
                        }
                        switch (genRand.Next(2))
                        {
                            case 0:
                                tile[col, row].frameY = 18;
                                break;
                            case 1:
                                tile[col, row].frameY = 36;
                                break;
                            case 2:
                                tile[col, row].frameY = 0;
                                break;
                        }
                        for (int k = 1; WorldMapper.TileTypeWDefs[tile[col, row - k].Tilebyte].colour == Constants.Colors.UNDERGROUNDMUSHROOM_TREES; k++)
                        {
                            tile[col, row - k].frameX = 0;
                            switch (genRand.Next(1))
                            {
                                case 0:
                                    tile[col, row].frameY = 18;
                                    break;
                                case 1:
                                    tile[col, row].frameY = 36;
                                    break;
                            }
                        }
                    }
                    if (WorldMapper.TileTypeWDefs[block.Tilebyte].colour == Constants.Colors.DOOR1 && !block.framelock)
                    {   
                        if (WorldMapper.TileTypeWDefs[tile[col + 1, row].Tilebyte].colour == Constants.Colors.DOOR1)
                        {
                            if (tile[col + 1, row - 1].active)
                            {
                                tile[col + 1, row].changeFrame(54, 0);
                                tile[col + 1, row + 1].changeFrame(54, 18);
                                tile[col + 1, row + 2].changeFrame(54, 36);

                                tile[col, row].changeFrame(36, 0);
                                tile[col, row + 1].changeFrame(36, 18);
                                tile[col, row + 2].changeFrame(36, 36);

                                tile[col, row].Tilebyte = 11;
                                tile[col, row + 1].Tilebyte = 11;
                                tile[col, row + 2].Tilebyte = 11;

                                tile[col + 1, row].Tilebyte = 11;
                                tile[col + 1, row + 1].Tilebyte = 11;
                                tile[col + 1, row + 2].Tilebyte = 11;

                            }
                            else
                            {
                                tile[col, row].changeFrame(0, 0);
                                tile[col, row + 1].changeFrame(0, 18);
                                tile[col, row + 2].changeFrame(0, 36);

                                tile[col + 1, row].changeFrame(18, 0);
                                tile[col + 1, row + 1].changeFrame(18, 18);
                                tile[col + 1, row + 2].changeFrame(18, 36);

                                tile[col, row].Tilebyte = 11;
                                tile[col, row + 1].Tilebyte = 11;
                                tile[col, row + 2].Tilebyte = 11;

                                tile[col + 1, row].Tilebyte = 11;
                                tile[col + 1, row + 1].Tilebyte = 11;
                                tile[col + 1, row + 2].Tilebyte = 11;
                            }
                        }
                        else
                        {
                            tile[col, row].changeFrame(18, 0);
                            tile[col, row + 1].changeFrame(18, 18);
                            tile[col, row + 2].changeFrame(36,36);
                        }
                    }


                    tile[col, row] = block;
                    
                }
            }

            //Actually write the world file

            writer.Write((Int32)Number); //Release Number Int32
            writer.Write((string)WorldName); //World Name string
            writer.Write((Int32)id); //Id Int32
            writer.Write((int)0); //World Coords Point 1 Int32
            writer.Write((int)(maxX * 16)); //World Coords Point 3 Int32
            writer.Write((int)0); //World Coords Point 2 Int32
            writer.Write((int)(maxY * 16)); //World Coords Point 4 Int32
            writer.Write((Int32)maxY); //Maxtiles X Int32
            writer.Write((Int32)maxX); //Maxtiles Y Int32
            writer.Write((Int32)spawningX); //SpawnPoint X Int32
            writer.Write((Int32)spawningY); //SpawnPoint Y Int32
            writer.Write((Double)sLv); //SurfaceLevel Double
            writer.Write((Double)rLv); //RockLayer Double
            writer.Write((Double)13500); //Temp Time Double
            writer.Write(true); //IsDay bool
            writer.Write((Int32)1.0); //Moon Phase Int32
            writer.Write(false); //IsBloodMoon bool
            writer.Write((Int32)0); //Dungeon X Int32
            writer.Write((Int32)0); //Dungeon Y Int32
            writer.Write((bool)boss1); //Boss1 Dead bool
            writer.Write((bool)boss2); //Boss2 Dead bool
            writer.Write((bool)boss3); //Boss3 Dead bool
            writer.Write(false); //ShadowOrbSmashed? bool
            writer.Write(false); //IsMetSpawn? bool
            writer.Write((byte)0); //# of orbs smashed byte
            writer.Write((Int32)0); //InvasionDelay Int32
            writer.Write((Int32)0); //InvasionSize Int32
            writer.Write((Int32)0); //InvasionType Int32
            writer.Write((Double)0); //InvationPointX Double

                for (int col = 0; col < maxX; col++)
                {
                    progressBar.ReportProgress((int)((((float)col / (float)maxX) * 2.0f) + 98f));
                    for (int row = 0; row < maxY; row++)
                    {
                        lock (tile[col,row]){
                        Block block = tile[col, row];
                        writer.Write(block.active);
                        if (block.active)
                        {
                            writer.Write(block.Tilebyte);


                            if (WorldMapper.TileTypeWDefs[block.Tilebyte].IsImportant)
                            {
                                    writer.Write((Int16)block.frameX);
                                    writer.Write((Int16)block.frameY);
                                    
                                }
                          

                        }
                        writer.Write(block.light);
                        writer.Write(block.wall);
                        if (block.isWall)
                        {
                            writer.Write((byte)block.wallbyte);
                        }
                        writer.Write(block.liquid);
                        if (block.isLiquid)
                        {
                            writer.Write(block.level);
                            writer.Write(block.lava);
                        }

                        }
                        //System.Diagnostics.Debug.WriteLine(progressBar.Value);
                    }
                }
                
                for (int i = 0; i < 0x3e8; i++)
                    {
                writer.Write(v.chests[i].isEnabled);
                if (v.chests[i].isEnabled)
                {
                    writer.Write((Int32)v.chests[i].X);
                    writer.Write((Int32)v.chests[i].y);
                    for (int k = 0; k < 20; k++)
                    {
                        writer.Write((byte)v.chests[i].items[k].count);
                        if (v.chests[i].items[k].count > 0)
                        {
                            writer.Write(v.chests[i].items[k].name);
                        }
                    }
                }
            }

                for (int i = 0; i < 0x3e8; i++)
            {
                writer.Write(v.signs[i].isActive);
                if (v.signs[i].isActive)
                {
                    writer.Write(v.signs[i].Text);
                    writer.Write((Int32)v.signs[i].X);
                    writer.Write((Int32)v.signs[i].Y);
                }
            }

            for (int i = 0; i < v.npc.Count; i++)
            {
                writer.Write(true);
                writer.Write(v.npc[i].name);
                writer.Write((Single)v.npc[i].X);
                writer.Write((Single)v.npc[i].Y);
                writer.Write(v.npc[i].hasHome);
                writer.Write((Int32)v.npc[i].HomeX);
                writer.Write((Int32)v.npc[i].HomeY);
            }

            writer.Write(false);
            writer.Write(true);
            writer.Write(WorldName);
            writer.Write(id);
            progressBar.ReportProgress(100);
            writer.Close();
            stream.Close();
        }

        protected static void Write7BitEncodedInt(BinaryWriter bin, int value)
        {
            uint num = (uint)value;
            while (num >= 0x80)
            {
                bin.Write((byte)(num | 0x80));
                num = num >> 7;
            }
            bin.Write((byte)num);
        }

        public void CreateReference()
        {
            string Filename = "";
            SaveFileDialog dialogW = new SaveFileDialog();
            dialogW.Filter = "Terraria Reference File (*.png)|*.png";
            dialogW.Title = "Select Reference File";
            dialogW.FileName = string.Format("{0}.png", System.IO.Path.GetFileNameWithoutExtension(Filename));
            string filePath = (dialogW.ShowDialog() == DialogResult.OK) ? dialogW.FileName : string.Empty;
            if (filePath == string.Empty)
            {
                return;
            }
            else if (new System.IO.FileInfo(filePath).Extension.ToUpper() != ".PNG")
            {
                MessageBox.Show("Reference File MUST End in .png", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Bitmap refI = new Bitmap(500, (colorTypeDefs.Count - (255 - Constants.MaxBlocks)) * 25);
            Graphics g = Graphics.FromImage(refI);
            int i = 0;
            foreach (Color c in colorTypeDefs.Keys)
            {
                if (i < Constants.MaxBlocks || i > 255)
                {
                    SolidBrush s = new SolidBrush(c);
                    string Name = "Unknown";
                    try
                    {
                        Name = TileTypeWDefs[i].TileType.ToString();
                    }
                    catch (KeyNotFoundException e)
                    {
                    }
                    int r = i;
                    if (r > Constants.MaxBlocks)
                    {
                        r -= (255 - Constants.MaxBlocks);
                    }
                    g.DrawString(Name, new Font("Times New Roman", 20), s, new Rectangle(0, r * 25, 350, 50));
                    g.FillRectangle(s, new Rectangle(350, r * 25, 150, 50));
                }
                    i++;
            }
            refI.Save(filePath);
        }

        public bool check2x2(int col, int row)
        {
            Block b = tile[col, row];
            Color c = WorldMapper.TileTypeWDefs[b.Tilebyte].colour;
            for (int i = 0; i < 1; i++)
            {
                for (int k = 0; k < 1; k++)
                {
                    if (WorldMapper.TileTypeWDefs[tile[col + i, row + k].Tilebyte].colour != c || tile[col + i, row + k].framelock)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        public bool check1x2(int col, int row)
        {
            Block b = tile[col, row];
            Color c = WorldMapper.TileTypeWDefs[b.Tilebyte].colour;
            if (WorldMapper.TileTypeWDefs[tile[col + 1, row].Tilebyte].colour != c || tile[col + 1, row].framelock)
                    {
                        return false;
                    }
            return true;
        }

        public bool check3x2(int col, int row)
        {
            Block b = tile[col, row];
            Color c = WorldMapper.TileTypeWDefs[b.Tilebyte].colour;
            for (int i = 0; i < 2; i++)
            {
                for (int k = 0; k < 1; k++)
                {
                    if (WorldMapper.TileTypeWDefs[tile[col + i, row + k].Tilebyte].colour != c || tile[col + i, row + k].framelock)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        

    }

    public class Imageing
    {
        Bitmap image;
        Bitmap WallI;
        System.ComponentModel.BackgroundWorker progressBar;
        int startX;
        int finishX;
        int startY;
        int finishY;
        int finalfinish;

        public Imageing(System.ComponentModel.BackgroundWorker p, int sX, int fX,int sY, int fY, int ffinish)
        {
            progressBar = p;
            finalfinish = ffinish;
            startX = sX;
            startY = sY;
            finishX = fX;
            finishY = fY;
            
        }
        /*
        public void analyse()
        {
            for (int col = startX; col < finishX; col++)
            {
                progressBar.ReportProgress((int)(((float)1 / finalfinish) * 98f));
                for (int row = startY; row < finishY; row++)
                {
                    Color pix = Color.FromArgb(WorldMapper.imagergb[((row * col) + (col * 4))], WorldMapper.imagergb[((row * col) + (col * 4) + 1)], WorldMapper.imagergb[((row * col) + (col * 4) + 2)]);
                    Color Wpix = Color.FromArgb(WorldMapper.Wallrgb[((row * col) + (col * 4))], WorldMapper.Wallrgb[((row * col) + (col * 4) + 1)], WorldMapper.Wallrgb[((row * col) + (col * 4) + 2)]);
                    Block block = WorldMapper.tile[col, row];
                    int by = Array.FindIndex(WorldMapper.colorTypeDefs, element => element.Equals(pix));
                    Color c = Array.Find(WorldMapper.colorTypeDefs, element => element.Equals(pix));

                    int byW = Array.FindIndex(WorldMapper.colorTypeDefs, element => element.Equals(Wpix));
                    Color cW = Array.Find(WorldMapper.colorTypeDefs, element => element.Equals(Wpix));

                    if (pix == Constants.Colors.SPAWN)
                    {
                        WorldMapper.spawningX = col;
                        WorldMapper.spawningY = row;
                        continue;
                    }

                    if (pix == Constants.Colors.UNKNOWN || pix == Constants.Colors.UNKNOWN)
                    {
                        block.Tilebyte = 0;
                    }

                    if (Wpix == Constants.Colors.UNKNOWN || Wpix == Constants.Colors.UNKNOWN)
                    {
                        block.wallbyte = 0;
                    }

                    if (pix == Constants.Colors.WATER)
                    {
                        block.liquid = true;
                    }
                    if (pix == Constants.Colors.LAVA)
                    {
                        block.liquid = true;
                        block.lava = true;
                        block.light = true;
                    }

                    Color[] Light = { Constants.Colors.CANDLE, Constants.Colors.CANDLEB, Constants.Colors.FURNACE, Constants.Colors.HELLSTONE, Constants.Colors.METEORITE, Constants.Colors.SORB, Constants.Colors.UFURNACE };
                    if (Array.Exists(Light, elements => elements.Equals(pix)))
                    {
                        block.light = true;
                    }

                    Color[] Wall = { Constants.Colors.WALL_BACKGROUND, Constants.Colors.WALL_BRICK, Constants.Colors.WALL_BRICKB, Constants.Colors.WALL_BRICKC, Constants.Colors.WALL_BRICKG, Constants.Colors.WALL_BRICKGO, Constants.Colors.WALL_BRICKHS, Constants.Colors.WALL_BRICKP, Constants.Colors.WALL_BRICKR, Constants.Colors.WALL_BRICKS, Constants.Colors.WALL_DIRT, Constants.Colors.WALL_STONE, Constants.Colors.WALL_STONE2, Constants.Colors.WALL_WOOD };
                    if (Array.Exists(Wall, elements => elements.Equals(Wpix)))
                    {
                        block.wall = true;
                        //active = false;
                        byW -= Constants.WallOffset;
                    }
                    string pixS = pix.ToString();
                    pixS = pixS.ToLower();

                    if (pix == Constants.Colors.SKY || pix == Constants.Colors.LAVA || pix == Constants.Colors.WATER)
                    {
                        block.active = false;
                    }

                    if (by >= 80)
                    {
                        block.active = false;
                        by = 0;
                    }
                    block.Tilebyte = (byte)by;
                    block.wallbyte = (byte)byW;

                    WorldMapper.tile[col, row] = block;
                }

            }
            WorldMapper.t1++;
        }
         */ 
    }
    }
